package cn.wk.config;

import cn.wk.access.MyAccessDeniedHandler;
import cn.wk.authentication.MyAuthenticationFailureHandler;
import cn.wk.authentication.MyAuthenticationSuccessHandler;
import cn.wk.domain.Permission;
import cn.wk.mapper.PermissionMapper;
import cn.wk.userdetail.MyUserDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;
import java.util.List;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private UserDetailsService userDetailsService;

   /* //内存中创建userdetail对象
    @Bean
    public UserDetailsService userDetailsServiceBean() throws Exception {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        inMemoryUserDetailsManager.createUser(User.withUsername("zs").password("123").authorities("admin").build());
        return inMemoryUserDetailsManager;
    }*/

    //密码编码器：不加密
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //记住我
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);  //设置数据库
        jdbcTokenRepository.setCreateTableOnStartup(false); //是否自动创建表
        return jdbcTokenRepository;
    }


    //授权规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //记住账号
        http.rememberMe()
                .tokenRepository(persistentTokenRepository())  //持久 调用的上面的
                .tokenValiditySeconds(60)     //过期时间
                .userDetailsService(userDetailsService);        //用来加载用户认证信息


        //设置权限路径
        //先去数据查询权限
        /*List<Permission> permissionList = permissionMapper.selectAll();
        permissionList.forEach(permission -> {
            try {
                http.authorizeRequests().antMatchers(permission.getResource()).hasAuthority(permission.getExpression());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });*/

        http.exceptionHandling().accessDeniedHandler(new MyAccessDeniedHandler());


        http.authorizeRequests()
                .antMatchers("/login","/login.html","/sms/send/*").permitAll()  //指定login路径放行
                .anyRequest().authenticated()       //其他请求要认证
                .and().formLogin()              //允许表单登录
                //.successForwardUrl("/successLogin")     //成功跳转登录页面
                .successHandler(new MyAuthenticationSuccessHandler())
                .failureHandler(new MyAuthenticationFailureHandler())
                .loginPage("/login.html")       //自定义登录页面
                .loginProcessingUrl("/login")   //登录提交地址
                .and().logout().permitAll()        //登出路径放行
                .and().csrf().disable();        //关闭跨域伪造检查
    }
}
